package net.xiake6.springcloud.commons.util.json;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import net.xiake6.springcloud.commons.enums.ApiMsgEnum;
import net.xiake6.springcloud.commons.exception.ComponentException;
import net.xiake6.springcloud.commons.vo.BaseReturnVO;

/**
 * @author Simon.Cheng
 * */
public class JsonUtil {
	

	private static ObjectMapper objectMapper;
	private static  final String RES_CODE="result";
	private static  final String RES_Data="data";
	private static  final String RES_DES="msg";
	
	static {
		objectMapper  = new ObjectMapper();
		objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 		// 非空不输出
		objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); // 时间格式

	}

	/**
	 * 将 JSON 字符串转为 Java 对象
	 */
	public static <T> T fromObject(Object objs, Class<T> type) {
		try {
			String json = toJSON(objs);
			return fromJSON(json,type);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 将 JSON 字符串转为 Java 对象
	 */
	public static <T> List<T> fromObjectArray(Object objs, Class<T> type) {
		try {
			String json = toJSON(objs);
			return fromJSONArray(json,type);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}


	/**
	 * 将 JSON 字符串转为 Java 对象
	 */
	public static <T> T fromFeign(String json, Class<T> type) {
		T obj;
		try {
		    int resultCode = getInteger(json,RES_CODE);
		    if(resultCode!= ApiMsgEnum.OK.getResCode()){
				String resDes = getString(json,RES_DES);
		    	throw  new ComponentException(resDes);
			}
			obj =  fromJSON(json,RES_Data,type);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return obj;
	}

	public static <T> List<T> fromFeignArray(String jsonStr, Class<T> elementClass) {
		try {
			int resultCode = getInteger(jsonStr,RES_CODE);
			if(resultCode!= ApiMsgEnum.OK.getResCode()){
				String resDes = getString(jsonStr,RES_DES);
				throw  new ComponentException(resDes);
			}
			return fromJSONArray(jsonStr,RES_Data,elementClass);
		} catch (Exception e)
		{
			throw new RuntimeException(e);
		}
	}




	/**
	 *
	 * @Description: 转换json串为泛型集合列表
	 * @remark 示例代码：json = [{\"name\":\"pyj1\",\"age\":\"28\"},{\"name\":\"pyj2\",\"age\":\"29\"}]
	 * 					List<User> users = convertJsonToList(json2,ArrayList.class,User.class);
	 * @param jsonStr json串
	 * @param elementClass 元素类
	 * @return
	 * @throws Exception
	 * @author
	 * @date
	 */
	public static <T> List<T> fromJSONArray(String jsonStr, String fieldName, Class<T> elementClass) {
		try {
			JsonNode node = objectMapper.readTree(jsonStr);
			JsonNode jsonNode = node.get(fieldName);
			if(jsonNode==null)
				return null;
			String  fieldJson = node.get(fieldName).toString();
			JavaType javaType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, elementClass);
			return (List<T>) objectMapper.readValue(fieldJson, javaType);
		} catch (Exception e)
		{
			throw new RuntimeException(e);
		}
	}

	public static <T> List<T> fromJSONArray(String jsonStr, Class<T> elementClass) {
		try {
			JavaType javaType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, elementClass);
			return (List<T>) objectMapper.readValue(jsonStr, javaType);
		} catch (Exception e)
		{
			throw new RuntimeException(e);
		}
	}



	/**
	 *
	 * @Description: 转换json串为泛型集合列表
	 * @remark 示例代码：json = [{\"name\":\"pyj1\",\"age\":\"28\"},{\"name\":\"pyj2\",\"age\":\"29\"}]
	 * 					List<User> users = convertJsonToList(json2,ArrayList.class,User.class);
	 * @param jsonStr json串
	 * @param elementClass 元素类
	 * @return
	 * @throws Exception
	 * @author
	 * @date
	 */
	public static <T> T fromJSON(String jsonStr, String fieldName, Class<T> elementClass) {
		try {
			JsonNode node = objectMapper.readTree(jsonStr);

			String  fieldJson = node.get(fieldName).toString();

			return  objectMapper.readValue(fieldJson, elementClass);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 将 JSON 字符串转为 Java 对象
	 */
	public static String getJsonString(String jsonStr, String fieldName) {
		try {
			JsonNode node = objectMapper.readTree(jsonStr);
			JsonNode fieldJson = node.get(fieldName);
			if(fieldJson==null)
				return "";
			return node.get(fieldName).toString();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 将 JSON 字符串转为 Java 对象
	 */
	public static String getString(String jsonStr, String fieldName) {
		try {
			JsonNode node = objectMapper.readTree(jsonStr);
			JsonNode fieldJson = node.get(fieldName);
			if(fieldJson==null)
				return "";
			return node.get(fieldName).textValue();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static Integer getInteger(String jsonStr, String fieldName) {
		try {
			JsonNode node = objectMapper.readTree(jsonStr);
			JsonNode jsonNode = node.get(fieldName);
			if(jsonNode==null) {
				return null;
			}
			return  castToInt(jsonNode.asText());
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static Integer getInteger(String jsonStr, String fieldName,int defVal) {
		try {
			JsonNode node = objectMapper.readTree(jsonStr);
			JsonNode jsonNode = node.get(fieldName);
			if(jsonNode==null) {
				return defVal;
			}
			return  castToInt(jsonNode.asText());
		} catch (Exception e) {
			//throw new RuntimeException(e);
			return defVal;
		}
	}


	public static Long getLong(String jsonStr, String fieldName) {
		try {
			JsonNode node = objectMapper.readTree(jsonStr);
			JsonNode jsonNode = node.get(fieldName);
			if(jsonNode==null){
				return null;
			}
			return  castToLong(jsonNode.asText());
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static BigDecimal getBigDecimal(String jsonStr, String fieldName) {
		try {
			JsonNode node = objectMapper.readTree(jsonStr);
			JsonNode jsonNode = node.get(fieldName);
			if(jsonNode==null){
				return null;
			}
			return  castToBigDecimal(jsonNode.asText());
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 将 JSON 字符串转为 Java 对象
	 */
	public static <T> T fromJSON(String json, Class<T> type) {
		T obj;
		try {
			obj = objectMapper.readValue(json, type);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return obj;
	}

	/**
	 * 将 JSON 字符串转为 Java 对象
	 */
	public static <T> T fromJSON(BaseReturnVO baseReturnVO, Class<T> type) {
		T obj;
		try {
			String json  =  JsonUtil.toJson(baseReturnVO.getData());
			obj = objectMapper.readValue(json, type);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return obj;
	}

	/**
	 * fromJSONArray 从BaseReturnVO 的data对象解析成List<T>
	 * @param baseReturnVO
	 *         [baseReturnVO]
	 * @param type
	 *         [type]
	 * @return java.util.List<T>
	 * @throws
	 * @author: jiang chao
	 * @date : 2018/9/17:14:37
	 */
	public static <T> List<T> fromJSONArray(BaseReturnVO baseReturnVO, Class<T> type) {
		try {
			String json  =  JsonUtil.toJson(baseReturnVO.getData());
			JavaType javaType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, type);
			return  (List<T>)objectMapper.readValue(json, javaType);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * fromJSON . 复杂泛型的json转换
	 * @remark  List<MailTaskStatusVO> result = JsonUtil.fromJSON(jsonData, new TypeReference<List<MailTaskStatusVO>>(){});
	 * @param jsonStr
	 *         [source]
	 * @param ref
	 *         [ref]
	 * @return T
	 * @throws
	 * @author: jiang chao
	 * @date : 2018/9/17:15:09
	 */
	public static <T> T fromJSON(String jsonStr, TypeReference<T> ref) throws Exception {
		T rtn = null;
		try
		{
			rtn = objectMapper.readValue(jsonStr, ref);
		}
		catch (IOException e)
		{
			throw e;
		}
		return rtn;
	}

	/**
	 * fromJSON .转换json串为泛型集合列表
	 * @remark  示例代码：JsonUtil.fromJSON(jsonStr, ArrayList.class,MailTaskStatusVO.class)
	 * @param jsonStr
	 *         [jsonStr]
	 * @param collectionClass
	 *         [collectionClass]
	 * @param elementClass
	 *         [elementClass]
	 * @return java.util.List<T>
	 * @throws
	 * @author: jiang chao
	 * @date : 2018/9/17:15:03
	 */
	public static <T> List<T> fromJSON(String jsonStr, Class<?> collectionClass,
			Class<T> elementClass) throws Exception {
		try {
			JavaType javaType = objectMapper.getTypeFactory()
					.constructParametricType(collectionClass, elementClass);
			return (List<T>) objectMapper.readValue(jsonStr, javaType);
		} catch (Exception e) {
			throw e;
		}
	}


	/**
	 * 将 Java 对象转为 JSON 字符串
	 */
	public static <T> String toJSON(T obj) {
		String jsonStr;
		try {
			jsonStr = objectMapper.writeValueAsString(obj);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return jsonStr;
	}


	
	public static String toJson(Object object) throws Exception{
		return objectMapper.writeValueAsString(object);
	}
	


	private static Integer castToInt(Object value){
		if(value == null){
			return null;
		}
		if(value instanceof Integer){
			return (Integer) value;
		}
		if(value instanceof Number){
			return ((Number) value).intValue();
		}
		if(value instanceof String){
			String strVal = (String) value;
			if(strVal.length() == 0 //
					|| "null".equals(strVal) //
					|| "NULL".equals(strVal)){
				return null;
			}
			if(strVal.indexOf(',') != 0){
				strVal = strVal.replaceAll(",", "");
			}
			return Integer.parseInt(strVal);
		}
		if(value instanceof Boolean){
			return ((Boolean) value).booleanValue() ? 1 : 0;
		}

		return null;
	}


	private static Long castToLong(Object value){
		if(value == null){
			return null;
		}
		if(value instanceof Number){
			return ((Number) value).longValue();
		}
		if(value instanceof String){
			String strVal = (String) value;
			if(strVal.length() == 0 //
					|| "null".equals(strVal) //
					|| "NULL".equals(strVal)){
				return null;
			}
			if(strVal.indexOf(',') != 0){
				strVal = strVal.replaceAll(",", "");
			}
			try{
				return Long.parseLong(strVal);
			} catch(NumberFormatException ex){
				//
			}
			return null;
		}
		return null;
	}

	public static BigDecimal castToBigDecimal(Object value){
		if(value == null){
			return null;
		}
		if(value instanceof BigDecimal){
			return (BigDecimal) value;
		}
		if(value instanceof BigInteger){
			return new BigDecimal((BigInteger) value);
		}
		String strVal = value.toString();
		if(strVal.length() == 0){
			return null;
		}
		if(value instanceof Map && ((Map) value).size() == 0){
			return null;
		}
		return new BigDecimal(strVal);
	}
}
